package com.system.service.imp;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.common.util.RedisUtil;
import com.core.system.domain.User;
import com.core.system.service.UserService;
import com.system.dto.ResourceDto;
import com.system.dto.UserDto;
import com.system.service.UserExService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.system.config.Constants.TOKEN_List;


@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserService userService;
    @Autowired
    private UserExService userExService;
    @Autowired
    private StringRedisTemplate template;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User one = userService.getOne(new LambdaQueryWrapper<User>()
                .eq( User::getLoginName, username));
        if(ObjectUtils.isEmpty(one)){
            throw new RuntimeException("用户名或密码错误");
        }
        one.setPassword( new BCryptPasswordEncoder().encode(one.getPassword()));
        List<ResourceDto> resourceDtoList = userExService.findUserResources(one.getId());
        UserDto userDto=new UserDto();
        BeanUtils.copyProperties(one,userDto);
        //设置权限
        HashSet<String> requestSet = getResquestStrings(resourceDtoList);
        userDto.setResources(getTreeResource(resourceDtoList));
        userDto.setAuthorities(requestSet);
        RedisUtil.setCacheObject(String.format(TOKEN_List,userDto.getId()),requestSet,3600l, TimeUnit.SECONDS);
        return userDto;
    }

    /**
     * 格式化成资源树
     *
     * @param resourceDtoList
     */
    private List<ResourceDto> getTreeResource(List<ResourceDto> resourceDtoList) {
        for (int i = resourceDtoList.size() - 1; i >= 0; i--) {
            // 当前要移动的记录
            ResourceDto child = resourceDtoList.get(i);
            // 如果当前节点没有父节点，则不用往下了
            if (StringUtils.isEmpty(child.getParent())) {
                continue;
            }
            // 查找父节点
            for (int j = resourceDtoList.size() - 1; j >= 0; j--) {
                ResourceDto parent = resourceDtoList.get(j);
                if (child.getParent().equals(parent.getId())) {
                    if (CollectionUtils.isEmpty(parent.getChildren())) {
                        parent.setChildren(new ArrayList<>());
                    }
                    // 添加到最前面，否则会变成倒序，因为循环是从后往前循环的
                    if (!parent.getChildren().contains(child)) {
                        parent.getChildren().add(0, child);
                    }
                    // 子节点找到父节点后，删除列表中的子节点
//                    resourceDtoList.remove(child);
                    if(parent.getChildren().size()>=2) {
                        Collections.sort(parent.getChildren(), Comparator.comparing(ResourceDto::getSort));//排序默认升序
                    }

                }
            }

        }
        List<ResourceDto> resourceDtoList1 = new ArrayList<>();
        for (int i = 0; i < resourceDtoList.size(); i++) {
            if (StringUtils.isEmpty(resourceDtoList.get(i).getParent())) {
                resourceDtoList1.add(resourceDtoList.get(i));
            }
        }
        if(!CollectionUtils.isEmpty(resourceDtoList1)) {
            Collections.sort(resourceDtoList1, Comparator.comparing(ResourceDto::getSort));
        }
        resourceDtoList.clear();
        return resourceDtoList1;
    }

    /**
     * 获取有权限的请求路径
     *
     * @param resourceDtoList
     * @return
     */
    private HashSet<String> getResquestStrings(List<ResourceDto> resourceDtoList) {
        HashSet<String> requestSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(resourceDtoList)) {
            for (int i = 0, l = resourceDtoList.size(); i < l; i++) {
                ResourceDto resourceDto = resourceDtoList.get(i);
                String arrayString = resourceDto.getRequest();
                List<String> requestList=new ArrayList<>();
                if(StringUtils.hasLength(arrayString)&&arrayString.startsWith("[")&&arrayString.endsWith("]")) {
                     requestList = JSON.parseArray(arrayString, String.class);
                }
                if (!CollectionUtils.isEmpty(requestList)) {
                    requestSet.addAll(requestList);
                }
            }
        }
        return requestSet;
    }

}
